package com.example.usercenter.config.security.token;

import com.example.usercenter.sys.entity.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * Created by zxn on 2018/7/30.
 */
@Component
public class TokenAuthenticationService {
    static final long EXPIRATIONTIME = 432_000_000;     // 5天
    static final String HEADER_TOKEN = "X-Token";// 存放Token的Header Key
    static final String PARAM_TOKEN = "token";// 存放Token的Header Key

    private static RedisTemplate<String, Object> redisTemplate;

    @Autowired
    public void setRedisTemplate(RedisTemplate<String, Object> redisTemplate) {
        TokenAuthenticationService.redisTemplate = redisTemplate;
    }

    public static String setAuthentication(User userDetail){
        String token = UUID.randomUUID().toString();
        redisTemplate.boundValueOps("X-Token:"+token).set(userDetail);
        redisTemplate.boundValueOps("X-Token:"+token).expire(EXPIRATIONTIME, TimeUnit.MILLISECONDS);
        return token;
    }

    // Token验证方法
    public static Authentication getAuthentication(HttpServletRequest request) {
        // 从Header中拿到token
        String token = request.getHeader(HEADER_TOKEN);
        if(token==null && "GET".equals(request.getMethod())){
            token = request.getParameter(PARAM_TOKEN);
        }
        if (token != null) {
            // 根据token从redis中获取用户信息
            User userDetail = (User)redisTemplate.opsForValue().get("X-Token:"+token);
            if(userDetail == null)
                return null;
            // 返回验证令牌
            return new UsernamePasswordAuthenticationToken(userDetail, userDetail.getPassword(), userDetail.getAuthorities());
        }
        return null;
    }
}
